package cn.xiaohaoo.admin.service;

import cn.xiaohaoo.admin.entity.SearchResult;
import org.bson.Document;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

@Service
public class MedicineService {
    @Autowired
    private MongoTemplate mongoTemplate;

    public List<Document> getAllMedicineOutlines() {
        return mongoTemplate.findAll(Document.class, "medicine_outline");
    }

    public List<Document> getAllMedicineOutlines(String name) {
        String regex = String.format("%s%s%s", "^.*", name, ".*$");
        Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
        Query query = new Query(Criteria.where("name").regex(pattern));
        return mongoTemplate.find(query, Document.class, "medicine_outline");
    }


    @Resource(name = "restHighLevelClient")
    private RestHighLevelClient restHighLevelClient;


    public List<Document> queryMedicineDetails(String keyword) throws IOException {
        QueryStringQueryBuilder queryBuilder = QueryBuilders.queryStringQuery(keyword);
        SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
        searchBuilder.query(queryBuilder);
        SearchRequest request = new SearchRequest("medicine_detail");
        HighlightBuilder highlightBuilder = new HighlightBuilder().field("*").requireFieldMatch(false);
        highlightBuilder.preTags("<span style=\"color:red\">");
        highlightBuilder.postTags("</span>");
        searchBuilder.highlighter(highlightBuilder);
        request.source(searchBuilder);
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        SearchHit[] searchHits = response.getHits().getHits();
        ArrayList<Document> documents = new ArrayList<>();
        for (SearchHit hit : searchHits) {
            Document document = new Document();
            document.put("nameSource", hit.getSourceAsMap().get("name"));

            for (HighlightField field : hit.getHighlightFields().values()) {
                StringBuilder stringBuilder = new StringBuilder();
                for (Text fragment : field.fragments()) {
                    stringBuilder.append(fragment.toString());
                }
                document.put(field.getName(), stringBuilder.toString());
            }
            documents.add(document);
        }
        return documents;
    }


    public Document queryMedicineDetail(String name) {
        Query query = new Query(Criteria.where("name").is(name));
        return mongoTemplate.findOne(query, Document.class, "medicine_detail");
    }


    public List<SearchResult> queryMedicineDetailsFromEs(String key) throws IOException {
        SearchRequest searchRequest = new SearchRequest("medicine");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        HighlightBuilder highlightBuilder = new HighlightBuilder().field(new HighlightBuilder.Field("*")
            .preTags("<span style='color: red'>").postTags("</span>"));
        searchSourceBuilder.query(QueryBuilders.queryStringQuery(key)).highlighter(highlightBuilder);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<SearchResult> results = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            if (hit != null) {
                SearchResult searchResult = new SearchResult();
                searchResult.setName(hit.getSourceAsMap().get("name").toString());
                for (HighlightField field : hit.getHighlightFields().values()) {
                    StringBuilder stringBuilder = new StringBuilder();
                    for (Text fragment : field.fragments()) {
                        stringBuilder.append(fragment.toString());
                    }
                    searchResult.getHits().put(field.getName(), stringBuilder.toString());
                }
                results.add(searchResult);
            }
        }
        return results;
    }
}
